﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using Dukou.Caching;
using Dukou.Security;
using Dukou.Security.BizService;
using Dukou.Security.Dao;
using Dukou.Security.Domain;
using Spring.Transaction.Interceptor;

namespace Dukou.Web.Security
{
    public class FormPassportService : IPassportService
    {
        /// <summary>
        /// 登录信息缓存
        /// </summary>
        private ICategoryCache<Guid, LogonInfo> _logonInfoCache;

        /// <summary>
        /// 角色缓存
        /// </summary>
        private ICategoryCache<Int64, IList<string>> _rolesCache;

        /// <summary>
        /// 特权缓存
        /// </summary>
        private ICategoryCache<Guid, IList<string>> _privilegesCache;

        /// <summary>
        /// 
        /// </summary>
        public ILogonInfoDao LogonInfoDao { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public IUserBizService UserBizService { get; set; }

        /// <summary>
        /// 设置 缓存服务
        /// </summary>
        public ICacheService CacheService
        {
            set
            {
                this._logonInfoCache = value.GetCategoryCache<Guid, LogonInfo>("__logoninfo");
                this._rolesCache = value.GetCategoryCache<Int64, IList<string>>("__roles");
                this._privilegesCache = value.GetCategoryCache<Guid, IList<string>>("privileges");
            }
        }

        [Transaction(ReadOnly = false)]
        public LogonInfo Logon(string userName, string password)
        {
            User user = this.UserBizService.FindByName(userName);
            if (user == null)
            {
                return null;
            }

            DateTime now = DateTime.Now;
            LogonInfo logonInfo = new LogonInfo()
            {
                Identifier = Guid.NewGuid(),
                SessionId = DukouContext.SessionID,
                IP = DukouContext.IP,
                Password = user.Password,
                User = user,
                LogonTime = now,
                RefreshTime = now,
            };

            this.LogonInfoDao.SaveOrUpdate(logonInfo);
            this._logonInfoCache.Add(logonInfo.Identifier, logonInfo);
            this._rolesCache.Add(user.Id, user.Roles.Select(x => x.Name).ToList());

            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
                        logonInfo.User.Name,
                        logonInfo.LogonTime,
                        logonInfo.LogonTime.AddYears(1),
                        false,
                        logonInfo.Identifier.ToString().ToUpper(),
                        FormsAuthentication.FormsCookiePath);
            string encTicket = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
            {
                //Domain = FormsAuthenticationHelper.Domain,
            };
            HttpContext.Current.Response.Cookies.Add(cookie);
            return logonInfo;
        }

        public void Logout()
        {
            if (!string.IsNullOrEmpty(DukouContext.UserData))
            {
                Guid guid = new Guid(DukouContext.UserData);
                this._logonInfoCache.Remove(guid);
                this._rolesCache.Remove(DukouContext.CurrentUser.Id);
                this._privilegesCache.Remove(guid);
            }
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName)
            {
                Expires = DateTime.MinValue,
            };
            HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        public LogonInfo FindByIdentifier(string identifier)
        {
            Guid guid = Guid.Empty;
            if (Guid.TryParse(identifier, out guid))
            {
                LogonInfo logonInfo = this._logonInfoCache.Get(guid);
                if (logonInfo == null)
                {
                    return this.LogonInfoDao.FindByIdentifier(new Guid(identifier));
                }

                return logonInfo;
            }

            return null;
        }
    }
}
